import { ZRenderComp } from '../../../common/component/zrComp';
import { cubicOut, cubicInOut, cubicIn } from '../../../common/animation';
import { seats, EVENT_BAN_SHOW, EVENT_BAN_HIDE, EVENT_ARROW, EVENT_SEAT } from "../../compute/events";
import { color, layouts, assets } from "./layout";

class BanBar extends ZRenderComp {
	/** @type {BanSeat[]} */
	banSeat = [];

	left = true;

	constructor(args) {
		super(args.parent, args.zrender);

		const left = this.left = args.left;
		this.layout = left ? layouts.banBars.left : layouts.banBars.right;
		this.useExistZRenderInstance(args.zr, this.layout.xSrc, this.layout.y);

		const seatNames = left ? seats.ban.left : seats.ban.right;
		this.banSeat = seatNames.map(seatName => new BanSeat({
			zrender: this.zrender, zr: this.zr, 
			parent: this, seatName, left
		}));

		// events
		this.on(EVENT_BAN_SHOW, this.onAnimate.bind(this, true));
		this.on(EVENT_BAN_HIDE, this.onAnimate.bind(this, false));
	}

	init() {
		const { layout } = this;
		this.spBg = this.createRect(layout.width, layout.height)
			.fill(color.banBars.bg)
			.z(0, 1)
			.build();
	}

	onAnimate(raise) {
		const { layout } = this;
		this.clearAnimations();
		this.getAnimX().update()
			.when(0, raise ? layout.xSrc : layout.xDst)
			.when(400, raise ? layout.xDst : layout.xSrc).easing(raise ? cubicOut : cubicIn)
			.commit();
	}
}

class BanSeat extends ZRenderComp {
	left = true;
	seatName = '';
	baseTime = 0; // 用于渐变 spGradient 的时间校准

	layout = {
		x: 0,
		y: 0,
		width: 0,
		height: 0,
		splitX: 0,
		splitY1: 0,
		splitY2: 0,
		splitWidth: 0
	};
	slashLayout = layouts.banSeat.slash;

	constructor(args) {
		super(args.parent, args.zrender);

		this.left = args.left;
		this.seatName = args.seatName;
		Object.assign(this.layout, layouts.banSeats[this.seatName]);
		this.useExistZRenderInstance(args.zr, this.layout.x, this.layout.y);

		// events
		this.on(EVENT_ARROW, this.onArrow.bind(this));
		this.on(EVENT_SEAT, this.onSelect.bind(this));
	}

	init() {
		const { layout, slashLayout, left } = this;

		// BL5 / BR5 没有这项
		if (this.seatName[2] != '5') {
			this.spSplit = this.createRect(layout.splitWidth, layout.splitY2 - layout.splitY1)
				.fill(color.banSeats.split)
				.position(layout.splitX, layout.splitY1)
				.z(0, 11)
				.build();
		}

		this.spSlash = this.createLine(slashLayout.x1, slashLayout.y1, slashLayout.x2, slashLayout.y2)
			.stroke(left ? color.banSeats.slashLeft : color.banSeats.slashRight, slashLayout.width)
			.opacity(1)
			.z(0, 5)
			.build();

		this.spGradient = this.createRect(layout.width, layout.height)
			.fillLinearGradient(0, 0, 0, 1, [
				{offset:0.05, color:left ? color.leftTransparent : color.rightTransparent},
				{offset:0.95, color:left ? color.left : color.right}
			])
			.z(0, 3)
			.build();
		this.spGradient.hide();
	}

	paint() {
		if (this.baseTime) {
			const duration = (Date.now() - this.baseTime) % 2000;
			this.spGradient.attr({
				style: {opacity: cubicInOut(Math.abs((duration - 1000) / 1000))}
			});
		}
		super.paint();
	}

	tick() {
		this.baseTime && this.makeDirty(false);
	}

	onArrow(_, param) {
		/** @type {string[]} */
		const seats = param.seats;
		if (!seats.find((seat) => seat === this.seatName)) {
			this.baseTime = 0;
			this.updateState();
			return;
		}

		if (this.baseTime) {
			return;
		}

		this.baseTime = Date.now();
		this.updateState();
	}

	onSelect(_, param) {
		/** @type {string} */ const seat = param.seat;
		if (this.seatName != seat) {
			return;
		}

		/** @type {string} */ const hero = param.hero;
		if (hero != '') {
			this.buildImage(hero);
		}
		this.updateState();
	}

	updateState() {
		// 正在选, hero==''      spSlash hide, spImage remove, spGradient show
		// 正在选, hero 存在     spSlash hide, spImage create, spGradient show
		// 不在选, hero==''      spSlash 是主题色, spImage remove, spGradient hide
		// 不在选, hero 存在     spSlash 是白的, spImage create, spGradient hide
		const selecting = this.baseTime != 0;
		const selected = this.root.banPick.seatSelect[this.seatName] != '';

		if (selecting) {
			this.spSlash.hide();
		} else {
			this.spSlash.attr({
				style: { stroke: selected ? color.white :
					(this.left ? color.banSeats.slashLeft : color.banSeats.slashRight) },
			});
			this.spSlash.show();
		}

		if (!selected) {
			this.removeImage();
		}
		selecting ? this.spGradient.show() : this.spGradient.hide();
	}

	removeImage() {
		this.spImage && this.spImage.destroy();
	}

	buildImage(hero) {
		const { layout } = this;
		this.removeImage();

		const url = this.root.context.assetPath(assets.banPathFunc(hero));
		this.spImage = this.createImage(url, layout.width, layout.height)
			.z(0, 2)
			.build();
	}
}

export {
	BanBar
};
